% Matlab script: mm1.m
% Proposito: Simula un modelo de cola con servidor simple del tipo
%			  M/M/1 con disciplina FIFO.
%			  Lee el archivo de entrada mm1.inp donde en el primer registro
%			  aparecen, separados por espacios: tiempo medio entre arribos, 
%			  tiempo medio de servicio y numero de clientes total procesados.
%			  La salida de la simulacion se da en dos archivos:
%			  mm1.out: Muestra valores estadisticos computados
%			  mm1.tim: Muestra la series de tiempo resultado de la simulacion
%			  
%			  Adaptado de "Simulation Modeling & Analysis", Law y Kelton.Proposito:     Simula una cola M/M/1
%
% Funciones utilizadas:
% arrive.m
% depart.m
% expon.m
% initialize.m
% report.m
% timing.m
% update_time_avg_stats.m
%
% Autor: Alejandro Diaz
% Declaracion de constantes y variables:
clear all

rand('seed', 13452);

global Q_LIMIT;
global BUSY;
global IDLE;

global next_event_type;
global num_custs_delayed;
global time_limit;
global num_events;
global num_in_q;
global server_status;

num_custs_delayed = cell(1, 2);
num_in_q = cell(1, 2);
server_status = cell(1, 2);

global area_num_in_q;
global area_server_status;
global total_time_in_system;
global mean_arrival_1;
global service_1_params;
global service_2_params;
global time;
global time_arrival;
global time_last_event;
global time_next_event;
global total_of_delays;

area_num_in_q = cell(1, 2);
area_server_status = cell(1, 2);
time_arrival = cell(1, 2);
total_of_delays = cell(1, 2);

global countE;
global countR;


%
Q_LIMIT = 100;
BUSY    = 1;
IDLE    = 0;

% Abre los archivos I/O
inpfile = fopen('mm1.inp','r');
global outfile;
outfile = fopen('mm1.out','w');

% Especifica el numero de eventos
%Entrada, salida de cola 1 a cola 2, realimentacion a cola 1, salida del
%sistema
num_events = 4;

% Lee el archivo de entrada
xdata = fscanf(inpfile,'%f %f %f %f %f %f',[1 6]);
mean_arrival_1 = xdata(1);
service_1_params(1) = xdata(2);
service_1_params(2) = xdata(3);
service_2_params(1) = xdata(4);
service_2_params(2) = xdata(5);
time_limit = xdata(6);
 

% Escribe los encabezados de los reportes y parametros de entrada
fprintf(outfile,'Sistema de colas de servidores\n\n');
fprintf(outfile,'Tiempo medio entre arribos %11.3f minutos\n\n',mean_arrival_1);
fprintf(outfile,'Tiempo medio de servicio_1 %11.3f a %11.3f minutos\n\n',service_1_params(1), service_1_params(2));
fprintf(outfile,'Tiempo medio de servicio_2 %11.3f a %11.3f minutos\n\n',service_2_params(1), service_2_params(2));
fprintf(outfile,'Tiempo de espera %14d\n\n', time_limit);

measuredW = zeros(1, 1300);
estimatedW = zeros(1, 1300);

relError = 1;
    
numTimes = 1;
acumW = 0;

variance = zeros(1, 1300);
desv = zeros(1, 1300);

while relError > 0.02
    % Inicializa la simulacion
    initialize();

    % Corre la simulacion
    while time < time_limit
        % Determina el proximo evento
        timing();

        % Actualiza los acumuladores estadisticos de tiempos medios
        update_time_avg_stats();

        % Invoca al evento apropiado
        switch (next_event_type)
            case 1
                arrive();
            case 2
                depart_from_queue_1();
            case 3
                depart_from_queue_2();
            case 4
                depart_from_queue_2();
        end

    end
    measuredW(numTimes) = total_time_in_system / (countE - countR);
    estimatedW(numTimes) = (acumW + total_time_in_system / (countE - countR)) / numTimes; 
    
    desv(numTimes) = std(measuredW(1:numTimes))/sqrt(numTimes);
    if desv(numTimes) ~= 0
        relError = desv(numTimes) / estimatedW(numTimes);
    end
    
    acumW = acumW + total_time_in_system / (countE - countR);
    numTimes = numTimes + 1;
end

estimatedW = estimatedW(1:numTimes);

% Invoca al generador de reportes y fin de la simulacion
%report(outfile);
fclose(inpfile);
fclose(outfile);